/**
 * 
 */
package jmine.tec.web.wicket.component.data.table.column;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.wicket.Component;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;

import bancosys.tec.persist.authorization.annotation.DisplayName;

/**
 * Column para {@link DisplayName}
 * 
 * @author takeshi
 */
public class DisplayNameColumn implements IColumn<Object>, Comparable<DisplayNameColumn> {

    private final String methodName;

    private final String className;

    private transient Method method;

    private transient DisplayName displayName;

    /**
     * @param method {@link Method}
     */
    public DisplayNameColumn(Method method) {
        super();
        this.method = method;
        this.className = method.getDeclaringClass().getName();
        this.displayName = method.getAnnotation(DisplayName.class);
        this.methodName = method.getName();
    }

    /**
     * {@inheritDoc}
     */
    public Component getHeader(String componentId) {
        return new Label(componentId, this.getDisplayName().value());
    }

    /**
     * {@inheritDoc}
     */
    public String getSortProperty() {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isSortable() {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public void populateItem(Item<ICellPopulator<Object>> cellItem, String componentId, IModel<Object> rowModel) {
        try {
            cellItem.add(new Label(componentId, String.valueOf(getMethod().invoke(rowModel.getObject()))));
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e.getTargetException());
        }
    }

    /**
     * {@inheritDoc}
     */
    public void detach() {
        this.method = null;
        this.displayName = null;
    }

    /**
     * {@inheritDoc}
     */
    public int compareTo(DisplayNameColumn o) {
        final int thisOrder = Integer.parseInt(this.getDisplayName().order());
        if (thisOrder == 0) {
            return 1;
        }
        final int thatOrder = Integer.parseInt(o.getDisplayName().order());
        if (thatOrder == 0) {
            return -1;
        }
        int cmp = thisOrder - thatOrder;
        if (cmp != 0) {
            return cmp;
        }
        return this.getDisplayName().value().compareTo(o.getDisplayName().value());
    }

    /**
     * @return the method
     */
    public Method getMethod() {
        if (this.method == null) {
            try {
                this.method = Class.forName(this.className).getMethod(this.methodName);
            } catch (SecurityException e) {
                throw new RuntimeException(e);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
        return method;
    }

    /**
     * @return the displayName
     */
    public DisplayName getDisplayName() {
        if (displayName == null) {
            this.displayName = this.getMethod().getAnnotation(DisplayName.class);
        }
        return displayName;
    }

}